// 枚举（Enum）类型用于取值被限定在一定范围内的场景，比如一周只能有七天，颜色限定为红绿蓝等。
const res = () => 120

enum Days {
    one, //手动赋值 如果没有赋值 默认 第一个为0
    two, //后面的值没有赋值会根据前面的值递增
    three, //这是自动递增 是2
    four = res(), //3
    five = one
}


// 字符串枚举是不能使用计算所得项的  可以使用其它成员
const stringres = () => "zks"

enum StringDa {
    a = "dasdsa",
    // b=stringres()//报错
    b = a.length
}

console.log(Days, 'days')
console.log(Days[1])
console.log(Days["one"])
console.log(StringDa, 'StringDa');


// 异构枚举

enum Gender {
    Male = 1,
    Female = "女"
}

console.log(Gender["Male"]);
console.log(Gender["Female"]);
console.log(Gender[2]);
console.log(Gender[1]);
console.log(Gender["女"]);

// 默认第一个值得类型必须是数字型  如果是字符串类型那么枚举类型不会进行自增需要手动全部添加
enum rgb {
    //   r = "201",//报错
    r = 201,
    g,
    b, //
}

// 枚举项有两种类型：常数项（constant member）和计算所得项（computed member）。
// 前面我们所举的例子都是常数项
// 字面枚举 表达式（基本上是字符串字面或数字字面）
// 对先前定义的常量枚举成员的引用（可以源自不同的枚举）
// 带括号的常量枚举表达式
// 应用于常量枚举表达式的 +、-、~ 一元运算符之一
// +、-、*、/、%、<<、>>、>>>、&、|、^ 以常量枚举表达式作为操作数的二元运算符  也是常数项


// enum Color { Red, Green, Blue = "blue".length };
// 上面的例子中，"blue".length 就是一个计算所得项。

enum Colors {
    Red,
    Green,
    Blue = "blue".length,
    //   yellow, //报错 无法获得初始值  需要手动赋值
}

// 常数枚举是使用 const enum 定义的枚举类型：它会在编译阶段被删除，并且不能包含计算成员。
const enum obj {
    up,
    down,
    left,
    right,
    // blue = "blue".length //报错   不能包含计算成员。
    sum = 1 + 1 //算作常数项枚举
    ,
    getNamee
}

console.log(obj.up);
console.log(obj.sum);


// 外部枚举（Ambient Enums）是使用 declare enum 定义的枚举类型： 用于声明文件
// 前提到过，declare 定义的类型只会用于编译时的检查 并不会打印结果，编译结果中会被删除。
declare enum ABC {
    a,
}

console.log(ABC.a);

// 同时使用 declare 和 const 也是可以的：

declare const enum abc {
    Up,
}

console.log(abc.Up);


enum Operator {
    ADD,
    DIV,
    MUL,
    SUB,
}

function compute(op: Operator, a: number, b: number) {
    switch (op) {
        case Operator.ADD:
            return a + b;
        case Operator.DIV:
            return a / b;
        case Operator.MUL:
            return a * b;
        case Operator.SUB:
            return a - b;
        default:
            throw new Error("wrong operator");
    }
}

compute(Operator.ADD, 1, 3); // 4


// UserE.admin 是一个 枚举成员访问表达式，它返回一个合法的枚举值（数字），所以可以赋值给枚举变量。
// 这是一个数值枚举只能赋值给数字类型变量 或者对应映射的枚举变量 ，ts

// 数值枚举
enum UserE {
    admin,
    user,
    guest
}

let UseUser: UserE
UseUser = UserE.admin
UseUser = 0
UseUser = 3
UseUser = "admin"  //报错


// 字符串枚举
enum UserE2 {
    admin = "admin",
    user = "user",
    guest = "guest"
}

let UseUser2: UserE2
UseUser2 = UserE2.admin
UseUser2 = "admin" //报错


enum UserE3 {
    guest,
    admin = "admin",
    user = "user",
}

let UseUser3: UserE3

UseUser3 = UserE3.admin
UseUser3 = 0
// UseUser3 = "admin"
// UseUser3 = 1


enum E {
    X,
    Y,
    Z,
}

function f(obj: { X: number }) {
    return obj.X;
}

f(E);